<?php
namespace app\madmin\model;
use databackup\Backup;
use think\Config;
use think\Model;
use think\Db;

/**
 * 备份模型类
 * @author  黄明杰 vx:HMJ125855
 * @version 20190101
 */
class SystemBackupModel extends Model
{

    protected $name = 'SystemBackup';

    /**
     * 数据列表方法
     * @param   Array   $Where      查询条件
     * @param   String  $Field      查询字段
     * @param   Int     $Limit      每页条数
     * @param   Srting  $Order      查询排序
     * @return  Array
     */
    public function mList($Where = [], $Field = '*', $Limit = 15, $Order = 'backup_id DESC'){
        $Count = $this->mCount($Where);

        $Where['backup_del'] = 1;

        return $this->field($Field)->where($Where)->order($Order)->paginate($Limit, $Count, ['query'=>request()->param()])->each(function($k, $v){
            $k->backup_create = date('Y/m/d H:i:s', $k->backup_create);
        });
    }

    /**
     * 数据统计方法
     * @param   Array   $Where      查询条件
     * @return  Int
     */
    public function mCount($Where = []){
        $Where['backup_del'] = 1;

        return $this->where($Where)->count();
    }

    /**
     * 数据详情方法
     * @param   Array   $Where      查询条件
     * @param   String  $Field      查询字段
     * @return  Array
     */
    public function mInfo($Where = [], $Field = '*'){
        $Where['backup_del'] = 1;

        return $this->field($Field)->where($Where)->find();
    }

    /**
     * 数据详情方法
     * @param   Array   $Where      查询条件
     * @param   String  $Field      查询字段
     * @return  String
     */
    public function mField($Where, $Field){
        $Where['backup_del'] = 1;

        return $this->where($Where)->value($Field);
    }

    /**
     * 数据新增方法
     * @param   Array   $Param      添加内容
     * @return  Array
     */
    public function mAdd($Param){
        $Code = 2;
        $Time = time();

        try{
            if($Param['backup_type'] == 1){
                $FileName = self::mTable($Param['backup_name']);
            }else if($Param['backup_type'] == 2){
                $FileName = self::mDatabase();
            }
            $Param['backup_file'] = $FileName;
            $Param['backup_create'] = $Time;

            $Result = $this->allowField(true)->insert($Param);

            $AddID = $this->getLastInsID();

            if($Result){
                $Code = 1;
                $Msgs = lang('XtTsTjCg');
            }else{
                $Msgs = lang('XtTsTjSb');
            }

            addMemberLog(session('AdminID'), 2, lang('XtBfRzXz', ['m'=>session('AdminUser'), 'd'=>$AddID]), $Code);

            return ['code'=>$Code, 'msgs'=>$Msgs, 'urls'=>url('SystemBackup/showList')];
        }catch(PDOException $e){
            return ['code'=>$Code, 'msgs'=>$e->getMessage()];
        }
    }

    /**
     * 数据还原方法
     * @param   Array   $Where      查询条件
     */
    public function mEdit($Where){
        $Code = 2;
        $Time = time();

        try{
            $Find = $this->mInfo($Where);

            if(empty($Find)){
                $Msgs = lang('XtCwCxCw');

                return ['code'=>$Code, 'msgs'=>$Msgs];
            }else{
                if($Find['backup_type'] == 2 || $Find['backup_name'] == 'db_table_list'){
                    $FileName = self::mTable('db_system_backup');
                }

                $Result = self::mReback($Find['backup_file']);
                
                if($Result){
                    $Code = 1;
                    $Msgs = lang('XtTsCzCg');

                    if($Find['backup_type'] == 2 || $Find['backup_name'] == 'db_table_list'){
                        if(self::mReback($FileName)){
                            @unlink(Config::get("backup.path").$FileName);
                        }
                    }
                }else{
                    $Msgs = lang('XtTsCzSb');
                }

                addMemberLog(session('AdminID'), 3, lang('XtBfRzHy', ['m'=>session('AdminUser'), 'd'=>$Where['backup_id']]), $Code);

                return ['code'=>$Code, 'msgs'=>$Msgs];
            }
        }catch(PDOException $e){
            return ['code'=>$Code, 'msgs'=>$e->getMessage()];
        }
    }

    /**
     * 数据下载方法
     * @param   Array   $Where      查询条件
     */
    public function mFile($Where){
        $Code = 2;

        try{
            $Find = $this->mInfo($Where);

            if(empty($Find)){
                $Msgs = lang('XtCwCxCw');

                return ['code'=>$Code, 'msgs'=>$Msgs];
            }else{
                $Code = 1;

                self::mDownload(Config::get("backup.path").$Find['backup_file']);
            }

            addMemberLog(session('AdminID'), 7, lang('XtBfRzBc', ['m'=>session('AdminUser'), 'd'=>$Where['backup_id']]), $Code);
        }catch(PDOException $e){
            return ['code'=>$Code, 'msgs'=>$e->getMessage()];
        }
    }


    /**
     * 数据删除方法
     * @param   Array   $Where      更新条件
     * @return  Array
     */
    public function mDel($Where){
        $Code = 2;
        $Time = time();

        try{
            $Where['backup_del'] = 1;

            $Param = [];
            $Param['backup_del'] = 2;
            $Param['backup_update'] = $Time;

            $BackupFile = $this->mField($Where, 'backup_file');

            $Result = $this->allowField(true)->where($Where)->update($Param);

            if($Result){
                $Code = 1;
                $Msgs = lang('XtTsScCs');

                @unlink(Config::get("backup.path").$BackupFile);
            }else{
                $Msgs = lang('XtTsScSb');
            }
 
            addMemberLog(session('AdminID'), 4, lang('XtBfRzSc', ['m'=>session('AdminUser'), 'd'=>$Where['backup_id']]), $Code);

            return ['code'=>$Code, 'msgs'=>$Msgs];
        }catch(PDOException $e){
            return ['code'=>$Code, 'msgs'=>$e->getMessage()];
        }
    }

    /**
     * 数据列表方法
     * @return  Array
     */
    public static function mTables(){
        $Bases = Db::getConfig();
        $Names = $Bases['database'];
        $Table = Db::query("show tables");

        $Lists = [];
        foreach($Table as $k => $v){
            $Lists[] = $v["Tables_in_$Names"];
        }

        return $Lists;
    }

    /**
     * 备份单张数据表
     * @param   String  $Table      备份表名
     * @return  String
     */
    private static function mTable($Table){
        $Db = new Backup();
        $Name = $Table.date('-Ymd-His');
        $File = ['name'=>$Name, 'part'=>1];
        $Data[] = $Table;
        
        $Db->repair($Data);
        $Db->optimize($Data);
        $Db->setFile($File)->backup($Table, 0);

        return $Db->getFile('filename');
    }

    /**
     * 备份整个数据库
     * @param   String  $Table      备份表名
     * @return  String
     */
    private static function mDatabase($Table = 'db_table_list'){
        $Db = new Backup();
        $Name = $Table.date('-Ymd-His');
        $File = ['name'=>$Name, 'part'=>1];
        
        $Db->setFile($File);
        
        $List = $Db->dataList();
        foreach($List as $k=>$v){
            $Data[] = $v['name'];
            $Db->backup($v['name'], 0);
        }
        
        $Db->repair($Data);
        $Db->optimize($Data);

        return $Db->getFile('filename');
    }

    /**
     * 还原备份文件
     * @param   String  $File       文件名称
     * @return  Bool
     */
    private static function mReback($File){
        $Db = new Backup();
        $Db->import(0, Config::get("backup.path").$File);

        return true;
    }

    /**
     * 备份下载
     * @param   String  $File       文件路径
     * @return  Nothing
     */
    public static function mDownload($File){
        if(file_exists($File)){
            ob_end_clean();
            header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
            header('Content-Description: File Transfer');
            header('Content-Type: application/octet-stream');
            header('Content-Length: '.filesize($File));
            header('Content-Disposition: attachment; filename='.basename($File));
            readfile($File);
        }else{
            throw new \Exception("{$File} File is abnormal");
        }
    }

}